package com.tepth.busfix.ic;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.tepth.busfix.R;
import com.tepth.busfix.ic.template.DeviceOperation;

import java.lang.ref.WeakReference;
import java.util.HashMap;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import cc.lotuscard.ILotusCallBack;
import cc.lotuscard.LotusCardDriver;
import cc.lotuscard.LotusCardParam;

import static cc.lotuscard.LotusCardDriver.m_InEndpoint;
import static cc.lotuscard.LotusCardDriver.m_OutEndpoint;
import static cc.lotuscard.LotusCardDriver.m_UsbDeviceConnection;
import static com.tepth.busfix.main.repair.NFCDialogActivity.NFC_RESULTCODE;

/**
 * Created by zhangyu on 2017/9/28.
 */

public class ICDialogActivity2 extends Activity implements ILotusCallBack {
    private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    @BindView(R.id.tv_device_note)
    TextView mTvDeviceNote;
    @BindView(R.id.pb_loading)
    ProgressBar mPbLoading;
    @BindView(R.id.tv_loading_msg)
    TextView mTvLoading;

    private UsbDeviceConnection m_LotusCardDeviceConnection = null;
    private static final int m_nVID = 1306;
    private static final int m_nPID = 20763;
    private static UsbDevice m_LotusCardDevice = null;
    private long mDeviceHandle = -1;
    private LotusCardDriver mLotusCardDriver;
    private Unbinder mUnBinder;
    private Handler mHandler = new Handler();
    private DeviceOperation mDeviceOperation;
    private String m_strDeviceNode;

    private boolean mStop = false;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ic_dialog);
        mUnBinder = ButterKnife.bind(this);
        if (!setUsbCallBack()) {
            mTvLoading.setText("未检测到打卡设备!");
        } else {
            mTvDeviceNote.setText(m_strDeviceNode);
            mLotusCardDriver = new LotusCardDriver();
            LotusCardDriver.m_lotusCallBack = this;
            doOperation();
        }
    }

    private boolean setUsbCallBack() {
        PendingIntent pendingIntent;
        pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(
                ACTION_USB_PERMISSION), 0);
        UsbManager m_UsbManager = (UsbManager) getSystemService(USB_SERVICE);
        if (null == m_UsbManager)
            return false;

        HashMap<String, UsbDevice> deviceList = m_UsbManager.getDeviceList();
        if (!deviceList.isEmpty()) {
            for (UsbDevice device : deviceList.values()) {
                if ((m_nVID == device.getVendorId())
                        && (m_nPID == device.getProductId())) {
                    m_LotusCardDevice = device;
                    m_strDeviceNode = m_LotusCardDevice.getDeviceName();
                    break;
                }
            }
        }
        if (null == m_LotusCardDevice)
            return false;
        UsbInterface m_LotusCardInterface = m_LotusCardDevice.getInterface(0);
        if (!m_UsbManager.hasPermission(m_LotusCardDevice)) {
            m_UsbManager.requestPermission(m_LotusCardDevice, pendingIntent);
        }
        UsbDeviceConnection conn = null;
        if (m_UsbManager.hasPermission(m_LotusCardDevice)) {
            conn = m_UsbManager.openDevice(m_LotusCardDevice);
        }

        if (null == conn)
            return false;

        if (conn.claimInterface(m_LotusCardInterface, true)) {
            m_LotusCardDeviceConnection = conn;
        } else {
            conn.close();
        }
        if (null == m_LotusCardDeviceConnection)
            return false;
        // 把上面获取的对性设置到接口中用于回调操作
        m_UsbDeviceConnection = m_LotusCardDeviceConnection;
        if (m_LotusCardInterface.getEndpoint(1) != null) {
            m_OutEndpoint = m_LotusCardInterface.getEndpoint(1);
        }
        if (m_LotusCardInterface.getEndpoint(0) != null) {
            m_InEndpoint = m_LotusCardInterface.getEndpoint(0);
        }
        return true;
    }

    private void doOperation() {
        new MyThread(this).start();
    }


    @OnClick(R.id.btn_cancel)
    public void onCancel() {
        mStop = true;
        if (mDeviceHandle != -1) {
            mLotusCardDriver.Halt(mDeviceHandle);
        }
        finish();
    }

    private void closeDevice() {
        if (mDeviceHandle != -1) {
            mLotusCardDriver.CloseDevice(mDeviceHandle);
            mDeviceHandle = -1;
        }
    }

    /**
     * 打开读卡设备
     */
    public void openDevice() {
        if (mDeviceHandle == -1) {
            mDeviceHandle = mLotusCardDriver.OpenDevice("", 0, 0, 0, 0,// 使用内部默认超时设置
                    true);
        }
        if (mDeviceHandle != -1) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mTvLoading != null) {
                        mTvLoading.setText("设备打开成功!正在唤醒蜂鸣器...");
                    }
                }
            });
            callBeep(mDeviceHandle);
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mTvLoading != null) {
                        mTvLoading.setText("设备打开失败!");
                    }
                }
            });

        }
    }

    /**
     * 唤醒蜂鸣器
     *
     * @param deviceHandle 设备句柄
     */
    private void callBeep(long deviceHandle) {
        if (!mLotusCardDriver.Beep(deviceHandle, 10)) {
            final int nErrorCode = mLotusCardDriver.GetErrorCode(deviceHandle);
            final String nErrorInfo = mLotusCardDriver.GetErrorInfo(deviceHandle, nErrorCode);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mTvLoading != null) {
                        mTvLoading.setText("蜂鸣器唤醒失败!" + nErrorCode + ":" + nErrorInfo);
                    }
                }
            });
            closeDevice();
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mTvLoading != null) {
                        mTvLoading.setText("蜂鸣器唤醒成功!");
                    }
                }
            });
            doStart();
        }
    }


    public void doStart() {
        int nRequestType = LotusCardDriver.RT_NOT_HALT;
        LotusCardParam tLotusCardParam1 = new LotusCardParam();
        while (!mStop) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (mLotusCardDriver.GetCardNo(mDeviceHandle, nRequestType,
                    tLotusCardParam1)) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mTvLoading != null) {
                            mTvLoading.setText("卡号读取成功!");
                        }
                    }
                });
                tLotusCardParam1.arrKeys[0] = (byte) 0xff;
                tLotusCardParam1.arrKeys[1] = (byte) 0xff;
                tLotusCardParam1.arrKeys[2] = (byte) 0xff;
                tLotusCardParam1.arrKeys[3] = (byte) 0xff;
                tLotusCardParam1.arrKeys[4] = (byte) 0xff;
                tLotusCardParam1.arrKeys[5] = (byte) 0xff;
                tLotusCardParam1.nKeysSize = 6;
                if (mLotusCardDriver.LoadKey(mDeviceHandle, LotusCardDriver.AM_A,
                        1, tLotusCardParam1)) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (mTvLoading != null) {
                                mTvLoading.setText("密钥加载成功!");
                            }
                        }
                    });
                    if (mLotusCardDriver.Authentication(mDeviceHandle,
                            LotusCardDriver.AM_A, 1, tLotusCardParam1)) {
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                if (mTvLoading != null) {
                                    mTvLoading.setText("密钥认证成功!");
                                }
                            }
                        });
                        byte[] data = new byte[48];
                        for (int i = 0; i < 3; i++) {
                            if (mLotusCardDriver.Read(mDeviceHandle, 4 + i, tLotusCardParam1)) {
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        if (mTvLoading != null) {
                                            mTvLoading.setText("读取成功!");
                                        }
                                    }
                                });
                                int j = i * 16;
                                for (int k = 0; k < 16; k++) {
                                    data[j++] = tLotusCardParam1.arrBuffer[k];
                                }
                                if (i >= 2) {
                                    int len = 0;
                                    for (int m = data.length - 1; m >= 0; m--) {
                                        if (data[m] != 0) {
                                            len = m;
                                            break;
                                        }
                                    }
                                    final byte[] finalData = new byte[len + 1];
                                    System.arraycopy(data, 0, finalData, 0, finalData.length);
                                    mStop = true;
                                    mLotusCardDriver.Halt(mDeviceHandle);
                                    mHandler.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            Intent result = new Intent();
                                            result.putExtra("BarCodeContents", finalData);
                                            setResult(NFC_RESULTCODE, result);
                                            closeDevice();
                                            finish();
                                        }
                                    });

                                }
                            }
                        }
                    } else {
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                if (mTvLoading != null) {
                                    mTvLoading.setText("认证失败!");
                                }
                            }
                        });
                    }
                } else {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (mTvLoading != null) {
                                mTvLoading.setText("密钥加载失败!");
                            }
                        }
                    });
                }
            } else {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mTvLoading != null) {
                            mTvLoading.setText("正在搜索IC卡...");
                        }
                    }
                });
            }
        }
    }

    private static class MyThread extends Thread {
        WeakReference<ICDialogActivity2> mThreadActivityRef;

        MyThread(ICDialogActivity2 activity) {
            mThreadActivityRef = new WeakReference<>(
                    activity);
        }

        @Override
        public void run() {
            if (mThreadActivityRef == null)
                return;
            if (mThreadActivityRef.get() != null)
                mThreadActivityRef.get().openDevice();
        }
    }

    @Override
    protected void onDestroy() {
        mUnBinder.unbind();
        mStop = true;
        super.onDestroy();
    }

    @Override
    public boolean callBackExtendIdDeviceProcess(Object objUser, byte[] arrBuffer) {
        return false;
    }

    @Override
    public boolean callBackReadWriteProcess(long nDeviceHandle, boolean bRead, byte[] arrBuffer) {

        int nResult = 0;
        boolean bResult = false;
        int nBufferLength = arrBuffer.length;
        int nWaitCount = 0;
        if (null == m_UsbDeviceConnection)
            return false;
        if (null == m_OutEndpoint)
            return false;
        if (null == m_InEndpoint)
            return false;
        // AddLog("callBackReadWriteProcess arrBuffer:" + Arrays.toString(arrBuffer));
        if (nBufferLength < 65)
            return false;
        if (bRead) {
            arrBuffer[0] = 0;
            while (true) {
                nResult = m_UsbDeviceConnection.bulkTransfer(m_InEndpoint,
                        arrBuffer, 64, 3000);
                if (nResult <= 0)
                    break;
                if (arrBuffer[0] != 0) {
                    //此处调整一下
                    System.arraycopy(arrBuffer, 0, arrBuffer, 1, nResult);
                    arrBuffer[0] = (byte) nResult;
                    break;
                }
                nWaitCount++;
                if (nWaitCount > 1000)
                    break;
            }
            // AddLog("m_InEndpoint bulkTransfer Read:"+nResult);
            if (nResult == 64) {
                bResult = true;
            } else {
                bResult = false;
            }
        } else {
            nResult = m_UsbDeviceConnection.bulkTransfer(m_OutEndpoint,
                    arrBuffer, 64, 3000);
            // AddLog("m_OutEndpoint bulkTransfer Write:"+nResult);
            if (nResult == 64) {
                bResult = true;
                //AddLog("m_OutEndpoint bulkTransfer Write Ok!");
            } else {
                bResult = false;
            }
        }
        return bResult;
    }
}
